Serialize and deserialize binary tree¶
Time: O(N); Space: O(H); medium
Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer environment.
Design an algorithm to serialize and deserialize a binary tree. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that a binary tree can be serialized to a string and this string can be deserialized to the original tree structure.
Example 1:
1
/ \
2 3
/ \
4 5
Input: root = {TreeNode} [1,2,3,#,#,4,5]
Output:
Serialize: “1 2 # # 3 4 # # 5 # #”
Deserialize: {TreeNode} [1,2,3,None,None,4,5]
Explanation:
just the same as how LeetCode OJ serializes a binary tree.
You do not necessarily need to follow this format, so please be creative and come up with different approaches yourself.
Notes:
Do not use class member/global/static variables to store states.
Your serialize and deserialize algorithms should be stateless.
[48]:
class TreeNode(object):
def __init__(self, x):
self.val = x
self.left = None
self.right = None
Auxiliary Tools¶
[49]:
from graphviz import Graph
class TreeTasks(object):
def visualize_tree(self, tree):
def add_nodes_edges(tree, dot=None):
# Create Graph (not Digraph) object
if dot is None:
dot = Graph()
dot.node(name=str(tree), label=str(tree.val))
# Add nodes
if tree.left and tree.left.val != "#":
dot.node(name=str(tree.left), label="."+str(tree.left.val))
dot.edge(str(tree), str(tree.left))
dot = add_nodes_edges(tree.left, dot=dot)
if tree.right and tree.right.val != "#":
dot.node(name=str(tree.right), label=str(tree.right.val)+".")
dot.edge(str(tree), str(tree.right))
dot = add_nodes_edges(tree.right, dot=dot)
return dot
# Add nodes recursively and create a list of edges
dot = add_nodes_edges(tree)
# Visualize the graph
display(dot)
return dot
Solution¶
[50]:
class Codec(object):
def serialize(self, root) -> str:
'''
Encodes a tree to a single string
:type root: TreeNode
:rtype: str
'''
def serializeHelper(node):
if not node:
vals.append('#')
else:
vals.append(str(node.val))
serializeHelper(node.left)
serializeHelper(node.right)
vals = []
serializeHelper(root)
return ' '.join(vals)
def deserialize(self, data) -> TreeNode:
'''
Decodes your encoded data (string) to tree
:type data: str
:rtype: TreeNode
'''
def deserializeHelper():
val = next(vals)
if val == '#':
return None
else:
node = TreeNode(int(val))
node.left = deserializeHelper()
node.right = deserializeHelper()
return node
def isplit(source, sep):
sepsize = len(sep)
start = 0
while True:
idx = source.find(sep, start)
if idx == -1:
yield source[start:]
return
yield source[start:idx]
start = idx + sepsize
vals = iter(isplit(data, ' '))
return deserializeHelper()
[51]:
codec = Codec()
# [1,2,3,#,#,4,5]
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.right.left = TreeNode(4)
root.right.right = TreeNode(5)
# 1. Serialize
s = codec.serialize(root)
assert s == "1 2 # # 3 4 # # 5 # #"
# 2. Deserialize
tree = codec.deserialize(s)
t = TreeTasks()
dot = t.visualize_tree(tree)
assert tree.val == 1
assert tree.left.val == 2
assert tree.right.val == 3
assert tree.right.left.val == 4
assert tree.right.right.val == 5